/* AUTHOR: Chris <MA_D> Hilton
 * LICENSE: GPLv2
 * PURPOSE:  Provide a second running thread to run items.
 */

/* Why me?
 * This file provides a sort of queue for functions on a second thread.
 * if the function returns 0 it is not called again, if it returns 1
 * it is put back on the end of the queue.
 * The functions are just called in order.  No interrupting ;).
 * That was a lie, there's now interrupting.
 * Here's what happens, your function gets called and others are 
 * allowed to add jobs while yours is going.  Now, when each job
 * is added it checks the timestap from when yours started.
 * If it's more than 180 seconds different from _now_, it kills
 * your function and moves onto the next one.
 * 
 * So your functions need to execute roughly inside of 3 minutes, 
 * preferably inside of 3 seconds though.  But I give as much leway
 * as possible do to the OS switching out the process and other
 * such things.  So, if you got a lot to do, find a way to do
 * it iteratively with your function, one iteration (or maybe 10)
 * per call!
 * 
 * NOTE:  As of now this library definitely isn't perfect.
 * In typical hard use you can't trip it up inside eJourn.
 * But, in tests I've managed to make it lose 1 out of 6 jobs.
 * I _think_ it has to do with the locks failing.  Because it
 * lost the same jobs with the locking off as with it on.
 * If you're a pthread_mutexattr expert, tell me how to make it
 * lock absolutely...
 */
 
#ifndef SECOND_H
#define SECOND_H

#include "error.h"

typedef unsigned long long timeout_t;

int elog_scnd_run_arg(int (* func) (void *), const char *id, void *dat);
//Note:  Just like elog_scnd_run, but you can put an argument into dat.

int elog_scnd_run(int (* func)(void *), const char *id);
//Pre: elog_scnd_initialize has been called
//Post:  adds this function to the end of the stack

/* timeout's are in milliseconds */
int elog_scnd_timeout(int (* func)(void *), const char *id,  timeout_t timeout);
//Note:  Just like elog_scnd_run, but with a timeout of time

int elog_scnd_timeout_arg(int (* func)(void *), const char *id, void *dat, timeout_t timeout);
//Note:  Just like elog_scnd_run_arg, but with a timeout of time



int elog_scnd_initialize();
//Pre:  You must call this before using any of the other functions.
//NOTE:  It should be safe and cheap to call as much as you wish.
//Post:  Gets everything ready to add jobs
	//Returns 0 on start, 1 if it was already running.

int elog_scnd_remove(const char *id);
//Pre:  id is a valid c string
//Post:  returns 0 if id is removed
	//1 if any sort of error occurs.

int elog_scnd_kill();
//Pre:  initialize has been called
//Post:  kills the current job, and starts back up.
//Returns 0 for kill, 1 for no reason to

int elog_scnd_still(const char *id);
//Pre:  id is a valid c string
//Post:  returns 1 if a job with id is still going, otherwise
// 0.

void elog_scnd_finish(int wait);
//Pre: wait is a number of time (in microseconds) to wait, or 0 for forever
//Post:  Waits that long before returning.  If you give 0 it waits until
// there are no more tasks.  If you have no non-ending tasks you may want to
//do this to insure that they finish.

#endif



